import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class Lambda {     //Lambda可以理解为：Lambda就是匿名内部类的简化，实际上是创建了一个类，实现了接口重写了接口的方法
    //无返回值无参数
    @FunctionalInterface   //检查是否为函数式接口(只有一个抽象方法)
    interface NoParameterNoReturn {
        void test();
    }
    //无返回值一个参数
    @FunctionalInterface
    interface OneParameterNoReturn {
        void test(int a);
    }
    //无返回值多个参数
    @FunctionalInterface
    interface MoreParameterNoReturn {
        void test(int a,int b);
    }

    public static void main1(String[] args) {
        NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {    //静态内部类
            @Override
            public void test() {
                System.out.println("hello");
            }
        };
        noParameterNoReturn.test();


    /* 无返回值的lambda表达式 */
        //Lambda可以理解为：Lambda就是匿名内部类的简化，实际上是创建了一个类，实现了接口重写了接口的方法
        //lambda表达式等价于静态内部类
        NoParameterNoReturn noParameterNoReturn1 = ()->{                //这句话表示有一个接口，没有参数，存在一个方法打印hello
            System.out.println("hello");
        };
        noParameterNoReturn.test();


        OneParameterNoReturn oneParameterNoReturn = (a)-> System.out.println(a+1);     //只有一个参数的时候可以省略参数类型 和 括号
        oneParameterNoReturn.test(10);


        MoreParameterNoReturn moreParameterNoReturn = (a,b)-> System.out.println(a+b); //类型不可以单独省略，必须一起省略,括号不能省略
        moreParameterNoReturn.test(15,20);
    }


    //有返回值无参数
    @FunctionalInterface
    interface NoParameterReturn {
        int test();
    }
    //有返回值一个参数
    @FunctionalInterface
    interface OneParameterReturn {
        int test(int a);
    }
    //有返回值多参数
    @FunctionalInterface
    interface MoreParameterReturn {
        int test(int a,int b);
    }

    /* 有返回值的lambda表达式 */
    public static void main2(String[] args) {
        NoParameterReturn noParameterReturn = ()->{return 10;};     //可以省略return
        int ret = noParameterReturn.test();
        System.out.println(ret);


        OneParameterReturn oneParameterReturn = x->{return x+10;};        //如果只有一条语句，那么就不需要{},并且可以省略return
        int ret1 = oneParameterReturn.test(9);
        System.out.println(ret1);

        MoreParameterReturn moreParameterReturn = (x,y)-> x+y;
        int ret2 = moreParameterReturn.test(15,20);
        System.out.println(ret2);
    }
    interface Test {
        void func();
    }
    public static void main3(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
//                a = 99;                   捕获到的不能是一个变量，必须是一个常量或者从未被修改过
                System.out.println("我是内部类，且重写了func这个方法！");
                System.out.println("我是捕获到变量 a == "+a
                        +" 我是一个常量，或者是一个没有改变过值的变量！");
            }
        }.func();


        OneParameterNoReturn oneParameterNoReturn = x-> {
//            a = 99;                        同样在lambda表示式中也必须是一个常量
            System.out.println(x+a);
        };
        oneParameterNoReturn.test(10);
    }


    /*
    lambda表达式在集合框架的使用
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("haha");
        list.add("ok");
        list.forEach(new Consumer<String>() {
            @Override
            //简单遍历集合中的元素。
            public void accept(String s) {
                System.out.print(s+" ");
            }
        });

        System.out.println();

        list.forEach(s -> System.out.print(s+" "));

        System.out.println();

//        list.sort(new Comparator<String>() {
//            @Override
//            public int compare(String o1, String o2) {
//                return o1.compareTo(o2);
//            }
//        });
        list.sort((o1,o2)-> o1.compareTo(o2));
        list.forEach(s -> System.out.print(s+" "));
        System.out.println();

        Map<String,Integer> hashMap = new HashMap<>();
        hashMap.put("hello",3);
        hashMap.put("abc",4);
        hashMap.put("ko",7);
        hashMap.forEach(new BiConsumer<String, Integer>() {
            @Override
            public void accept(String s, Integer integer) {
                System.out.println("key : "+s+" value : "+integer);
            }
        });
        hashMap.forEach((s,a)-> System.out.println("key : "+s+" value : "+a));
    }
}
